/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.model;

import java.io.Serializable;
import javax.jdo.annotations.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import nl.cloudfarming.client.util.GeometryUtil;

/**
 * Link between cropprotection and a task + data for that task with that cropprotection as action
 * 
 * @author Gerben Feenstra
 */
@NamedQueries(value = {
    @NamedQuery(name = CropProtectionTask.Q_FIND_ALL_CROPPROTECTIONTASKS, query = "select cpt from CropProtectionTask cpt"),
    @NamedQuery(name = CropProtectionTask.Q_FIND_CROPPROTECTIONTASKS_BY_ID, query = "select cpt from CropProtectionTask cpt where cpt.id = :id")
})
@Entity
@Table(name = "CROP_PROTECTION_TASK")
public class CropProtectionTask extends Task implements Serializable, Persistable {

    public static final String Q_FIND_ALL_CROPPROTECTIONTASKS = "findAllCropProtectionTasks";
    public static final String Q_FIND_CROPPROTECTIONTASKS_BY_ID = "findCropProtectionTasksById";
    private final double DEVIATION = 0.0001;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CROP_PROTECTION_ID")
    private CropProtection cropProtection;
    @Column(name = "CONCENTRATION")
    private Double concentration;
    @Column(name = "QUANTITY")
    private Double quantity;

    public Double getQuantity() {
        return quantity;
    }

    public void setQuantity(Double quantity) {
        Double old = this.quantity;
        this.quantity = quantity;
        getPropertyChangeSupport().firePropertyChange("quantity", old, quantity);
        fireUndoableEvent("quantity", this, old, quantity);

        if (getOperation() != null && getOperation().getProductionUnit() != null) {
            Double value = quantity / GeometryUtil.getAcreageInHA(getOperation().getProductionUnit().getAcreage());
            Double oldConcentration = this.concentration;
            this.concentration = value;
            getPropertyChangeSupport().firePropertyChange("concentration", oldConcentration, value);
        }
    }

    public Double getConcentration() {
        return concentration;
    }

    public void setConcentration(Double concentration) {
        Double old = this.concentration;
        this.concentration = concentration;
        getPropertyChangeSupport().firePropertyChange("concentration", old, concentration);
        fireUndoableEvent("concentration", this, old, concentration);

        if (getOperation() != null && getOperation().getProductionUnit() != null) {
            Double value = concentration * GeometryUtil.getAcreageInHA(getOperation().getProductionUnit().getAcreage());
            Double oldQuantity = this.quantity;
            this.quantity = value;
            getPropertyChangeSupport().firePropertyChange("quantity", oldQuantity, value);
        }
    }

    public CropProtection getCropProtection() {
        return cropProtection;
    }

    public void setCropProtection(CropProtection cropProtection) {
        CropProtection old = this.cropProtection;
        this.cropProtection = cropProtection;
        getPropertyChangeSupport().firePropertyChange("cropProtection", old, cropProtection);
        fireUndoableEvent("cropProtection", this, old, cropProtection);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        if(!super.equals(obj)){
            return false;
        }
        final CropProtectionTask other = (CropProtectionTask) obj;
        if (this.cropProtection != other.cropProtection && (this.cropProtection == null || !this.cropProtection.equals(other.cropProtection))) {
            return false;
        }
        if (this.concentration != other.concentration && (this.concentration == null || !this.concentration.equals(other.concentration))) {
            return false;
        }
        if (this.quantity != other.quantity && (this.quantity == null || !this.quantity.equals(other.quantity))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = super.hashCode();
        hash = 71 * hash + (this.cropProtection != null ? this.cropProtection.hashCode() : 0);
        hash = 71 * hash + (this.concentration != null ? this.concentration.hashCode() : 0);
        hash = 71 * hash + (this.quantity != null ? this.quantity.hashCode() : 0);
        return hash;
    }

    public static class Builder {

        private CropProtectionTask cropProtectionTask;

        public Builder() {
            cropProtectionTask = new CropProtectionTask();
        }

        public Builder setQuantity(Double quantity) {
            cropProtectionTask.setQuantity(quantity);
            return this;
        }

        public Builder setConcentration(Double concentration) {
            cropProtectionTask.setConcentration(concentration);
            return this;
        }

        public Builder setCropProtection(CropProtection cropProtection) {
            cropProtectionTask.setCropProtection(cropProtection);
            return this;
        }

        public Builder setOperation(Operation operation) {
            cropProtectionTask.setOperation(operation);
            return this;
        }

        public CropProtectionTask build() {
            return cropProtectionTask;
        }
    }
}
